/**
 *
 */
package vn.smartware.co.framework.db.factory;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import vn.smartware.co.framework.exception.ServerException;

/**
 * SQLManager
 * @author thuctt
 */
public class SQLManager {

//	private String sql;
	private PreparedStatement statement;
	private static Log log = LogFactory.getLog(SQLManager.class);

//	/**
//	 * precompilePreparedStatement
//	 * 
//	 * @param sql
//	 * @param con
//	 * @throws SQLException
//	 */
//	public void precompilePreparedStatement(String sql, Connection con)
//			throws SQLException {
//		this.sql = sql;
//		setPreparedStatement(con.prepareStatement(getSql()));
//	}
//
//	/**
//	 * precompilePreparedStatement
//	 * 
//	 * @param sql
//	 * @param con
//	 * @param resultSetType
//	 * @param resultSetCon
//	 * @throws SQLException
//	 */
//	public void precompilePreparedStatement(String sql, Connection con,
//			int resultSetType, int resultSetCon) throws SQLException {
//
//		this.sql = sql;
//		setPreparedStatement(con.prepareStatement(getSql(), resultSetType,
//				resultSetCon));
//	}
//
//	/**
//	 * precompileCallableStatement
//	 * 
//	 * @param sql
//	 * @param con
//	 * @throws SQLException
//	 */
//	public void precompileCallableStatement(String sql, Connection con)
//			throws SQLException {
//
//		this.sql = sql;
//		setPreparedStatement(con.prepareCall(getSql()));
//	}
//
//	/**
//	 * precompilePreparedStatement
//	 * 
//	 * @param ps
//	 */
//	public void precompilePreparedStatement(PreparedStatement ps) {
//		setPreparedStatement(ps);
//	}
//
//	/**
//	 * precompileCallableStatement
//	 * 
//	 * @param cs
//	 */
//	public void precompileCallableStatement(CallableStatement cs) {
//		setPreparedStatement(cs);
//	}

	/**
	 * closePreparedStatement
	 * 
	 * @throws SQLException
	 */
	public void close() throws SQLException {
		if (null != this.statement){
			this.statement.close();
		}else{
			throw new SQLException("SQLManager closePreparedStatement Can not be NULL.");
		}
	}

	/**
	 * closeCallableStatement
	 * 
	 * @throws SQLException
	 */
	public void closeCallableStatement() throws SQLException {
		close();
	}

	/**
	 * execute
	 * 
	 * @return boolean
	 * @throws SQLException
	 */
	public boolean execute() throws SQLException {
		return getPreparedStatement().execute();
	}

	/**
	 * executeQuery
	 * 
	 * @return ResultSet
	 * @throws SQLException
	 */
	public ResultSet executeQuery() throws SQLException {
		return getPreparedStatement().executeQuery();
	}

	/**
	 * executeUpdate
	 * 
	 * @return result
	 * @throws SQLException
	 */
	public int executeUpdate() throws SQLException {
		return getPreparedStatement().executeUpdate();
	}

	/**
	 * @return ps
	 */
	public PreparedStatement getPreparedStatement() {
		return statement;
	}

	/**
	 * @return statement CallableStatement
	 */
	public CallableStatement getCallableStatement() {
		return (CallableStatement) statement;
	}

	/**
	 * @param ps
	 */
	public void setPreparedStatement(PreparedStatement ps) {
		this.statement = ps;
	}

//	/**
//	 * @return sql
//	 */
//	public String getSql() {
//		return sql;
//	}
//
//	/**
//	 * @param sql
//	 */
//	public void setSql(String sql) {
//		this.sql = sql;
//	}
	
	/**
	 * close statement and resultset
	 * @param rs
	 * @throws SQLException
	 */
	public void close(ResultSet rs) throws SQLException {
		if (rs != null) {
			rs.close();
		}
	}
	
	protected void compileQuery(Connection conn, String sql, String param) throws ServerException {
		try {
			this.statement = conn.prepareStatement(sql);
			this.statement.setString(1, param);
			//
			String sqlLog = sql;
			sqlLog.replaceFirst("?", param.toString());
			log.debug(sqlLog);
		}
		catch (SQLException e) {
			throw new ServerException("SQLException.", e);
		}		
	}
	
	protected void compileQuery(Connection conn, String sql, List<Object> params) throws ServerException {
		try {
			String sqlLog = sql;
			this.statement = conn.prepareStatement(sql);
			int i = 1;
			for (Object param : params) {
				this.statement.setObject(i++, param);
				sqlLog.replaceFirst("?", param.toString());
			}
			log.debug(sqlLog);
		}
		catch (SQLException e) {
			throw new ServerException("SQLException.", e);
		}		
	}
}
